<html>
<!-- $LastChangedDate: 2011-09-09 09:46:35 -0400 (Fri, 09 Sep 2011) $ -->
<!-- Copyright (C) 2004,2009 Jim Brooks http://www.palomino3d.org -->
<head>
<title>Palomino - Control Module</title>
<link rel='stylesheet' type='text/css' href='docs.css'>
<link rel='icon' type='image/png' href='images/favicon.png'/>
</head>
<body>

<!-- ----------------------------------------------------------------------- -->
<h1>Palomino - Control Module</h1>
<p>
&copy;2004,2009&nbsp;&nbsp;Jim E. Brooks
&nbsp;&nbsp;<a href='http://www.palomino3d.org'>http://www.palomino3d.org</a>
</p>
<hr>
<ul>
  <li><a href='index.html'>Index</a></li>
  <li><a href='#Overview'>Overview</a></li>
  <li><a href='#Control of Aircraft'>Control of Aircraft (Current Craft)</a></li>
  <li><a href='#Joystick'>Joystick</a></li>
  <li><a href='#Command Events'>Command Events</a></li>
  <li><a href='#Replay'>Replay</a></li>
  <li><a href='#Lua Scripting'>Lua Scripting</a></li>
</ul>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Overview'></a>
<h2>Overview</h2>
<p><!--date-->[2008/05]</p>
<p>
The control module is a higher-level module (Mediator class)
that handles system-neutral input propagated by the lower-level input module.
control module has the joystick configuration.  If the joystick is enabled,
control will manipulate the current Aircraft in response to joystick events.
The control module no longer needs to be involved in keyboard handling
(see <a href='#Lua Scripting'>Lua Scripting</a>).
</p>
<p>
<ul>
<li>Defines the "current" Aircraft</li>
<li>Controls the current Aircraft by joystick (if enabled).</li>
<li>Defers processing of button events to listeners
  (asymmetrically, control handles axis events).
</li>
<li>Has joystick configuration.</li>
</ul>
</p>
<p>
<pre>
+----------------+
|   application  |
+----------------+
| control module |
+----------------+
|   input module |
+----------------+
| device drivers |
+----------------+
</pre>
</p>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Current Craft'></a>
<a name='CurrentCraft'></a>
<a name='Control of Aircraft'></a>
<a name='Control of Craft'></a>
<h2>Control of Aircraft (Current Craft)</h2>
<p><!--date-->[2008/01]</p>
<p>
An aircraft's rate-of-roll/pitch/yaw is computed by the physics code.
The joystick/keyboard handlers in the control module
rotate the "current craft" by calling Aircraft::PhysicalRotate().
Args passed are the level of control input (0.0,..,1.0 : 1.0 is all-the-way)
and the frequency of polling control input.
Internally, PhysicalRotate() computes an absolute/graphical degree
that is passed to Aircraft::Rotate().
</p>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Joystick'></a>
<h2>Joystick</h2>
<p><!--date-->[2008/01..2009/11]</p>
<p>
There are two unrelated Joystick classes:
<a href='module_input.html#Joystick'>input::JoystickDevice</a> and control::Joystick.
<br>This documents control::Joystick.
</p>
<p>
control::Joystick is the higher-level joystick class.
It is a client of the low-level <a href='module_input.html#Joystick'>input::JoystickDevice</a>.
Input::JoystickDevice is basic: it enqueues joystick events but does no final actions.
control::Joystick contains the higher-level joystick functionality.
It does enabling, configuring, remapping, calibrating, and some handling of events.
It handles axis events by <a href='#Control of Aircraft'>controlling the current Craft</a>.
But it defers button events to listeners in the application (Lua scripts).
<p>
<p>
control::Joystick is based on a joystick with 4 logical axises (roll/pitch/yaw/throttle).
Joystick configuration is defined by joystick.conf.
The configuration defines the mapping between logical and physical axises,
and axis calibration.
</p>
<h3>Logical joystick axises</h3>
<p>
The higher-level joystick code is based on 4 logical axises.
</p>
<pre>
0 = roll  (left/right)  joy X by convention
1 = pitch (up/down)     joy Y by convention
2 = yaw
3 = throttle            
</pre>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Command Events'></a>
<a name='Command'></a>
<h2>Command Events</h2>
<p><!--date-->[2008/08]</p>
<p>
The simulator abstracts control of a Aircraft in a <code>Command</code> object.
The Aircraft class broadcasts control actions (rotation, throttle, brakes, etc)
in events containing a Command object.
Conversely, a Command object can apply a command to a Aircraft.
</p>
<p>
For example, <a href='#Replay'>Replay</a> listens for Command events for 
a particular Aircraft and stores Commands in a container.
To do a replay, Command::Execute(Aircraft) is called for every stored Command.
</p>
<p>
Command events could be used to network simulators.
</p>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Replay'></a>
<h2>Replay</h2>
<p><!--date-->[2008/09]</p>
<p>
Replay registers a listener for <a href='#Command'>Command</a> events
(roll, throttle, brakes, gear-down, etc) from a particular Aircraft.
Replay stores Command objects with a time-stamp (Step class) in a STL container.
To do a replay, the commands are replayed by calling Command::Execute(Aircraft).
</p>
<h3>Control Replay vs. Graphical Replay</h3>
<p>
<i>Control replay</i> means replaying events from input while being affected by the physics model.
<i>Graphical replay</i> means replaying abstract graphical transformations.
For example, recording a replay while piloting a F-15 Eagle,
then applying a <i>graphical replay</i> to a Spitfire would be unrealistic.
But, applying a saved replay to Aircrafts with similar performance may be interesting.
Therefore, Replay records both types of data, but can replay either type (or a mixture) as needed.
</p>
<h3>Implementation</h3>
<p>
To save space, the replay data is compressed by zlib,
rotations are stored as quaternions, and only steps that change (keyframes) are stored.
Since graphical coordinates vary according to different missions,
the position of a Aircraft converted to geo coordinates before storing.
Replay::Play() can be passed a parameter to animate replays in different geo positions..
</p>
<p>
Replay data is saved to a file compressed using zlib (replay.dat.gz).
Writing is done using <code>gzstream</code>.
The format is human-readable.
The first line is the version info (replay format).
The following few lines provide other info and initial state.
The bulk of the lines are commands to control a Aircraft,
which begin with a time-stamp field (milliseconds),
then the serialized Command.
When recording first starts, the current state of the Aircraft is saved
(the lines with milliseconds=0).
In physics replay mode, <code>phyRot</code> (rotate using physics)
are applied while <code>qaut</code> (graphical rotation) are ignored.
</p>
<pre>
version 3
craft F18Aircraft
world flat
0 pos 8007 -15527.5 -528.25 
0 quat 0.710016 0.0154926 0.015358 0.703847  
0 throt 0 
0 kph 0 
0 gear 1 
0 brake 0 
363 throt 0.0629749 
396 pos 7997 -15697 -528.25 
443 kph 2.33392 
458 throt 0.988189
3842 pos 7987.05 -15630.4 -528.25 
3945 quat 0.70991 0.0527554 0.0520474 0.700383  
</pre>
<p>
Replay is factored as these classes:
</p>
<ul>
<li>Replay</li>
<li>ReplayRecorder</li>
<li>ReplayPlayer</li>
<li>ReplayPath (data class)</li>
<li>ReplayPath::Step (Command with time-stamp)</li>
<li>ReplayPath::Cursor (tracks current set of steps in animation path)</li>
<li>Command (affects a Aircraft)</li>
</ul>
<p>
The class Replay is the interface.
ReplayRecorder and ReplayPlayer both contain shared pointer to a ReplayPath.
After recording, the player is given the shared pointer to the recorded path.
</p>
<p>
ReplayPath::Cursor naturally tracks the current step in the animation path.
But it also will lookahead to future steps that control position/rotation.
Cursor maintains a pair of position/rotation steps that the player will interpolate
to smooth animation across timer-ticks that occur late (if program is running slow).
</p>

<!-- ----------------------------------------------------------------------- -->
<hr>
<a name='Lua Scripting'></a>
<h2>Lua Scripting</h2>
<p><!--date-->[2008/05]</p>
The control module once had keyboard handling, but was eliminated after
keyboard handlers were implemented by Lua scripts which directly use InputQueue.
</p>
<p>
The joystick C++ code in the control module survives because
it's faster than Lua and its handling of axis events remains appropriate.
But handling of button events is mission-specific, so the lua_bind module
(sim.Joystick in Lua) registers a listener and provides an interface
for Lua scripts to poll for button events.
In summary, the control::Joystick interface remains the same as in
previous versions but is used differently for Lua scripting.
<p>

<!-- ********************************* END ********************************* -->
<hr>
<p align='center'>
<font size='-2'>
<!-- hhmts start -->
Last modified: Fri Sep  9 01:10:20 EDT 2011
<!-- hhmts end -->
</font>
</p>

</body>
</html>
